package jfprincesstests.structures.negotiation;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import jfprincesstests.fakes.FakeCondition;
import jfprincesstests.fakes.FakeWhileAgent;
import jfprincesstests.fakes.FakeWhileNegConstr;
import jfuzzyprincepless.agents.BaseNegotiationAgent;
import jfuzzyprincepless.agents.INegotiatingAgent;
import jfuzzyprincepless.algorithm.structure.CompoundConstruction;
import jfuzzyprincepless.algorithm.structure.DefaultNegConstruction;
import jfuzzyprincepless.algorithm.structure.IConstruction;
import jfuzzyprincepless.algorithm.structure.INegotiationConstruction;
import jfuzzyprincepless.negotiation.DefaultNegotiation;
import jfuzzyprincepless.negotiation.DefaultNegotiationContext;
import jfuzzyprincepless.negotiation.INegotiationContext;
import jfuzzyprincepless.negotiation.services.IAgentsListService;
import jfuzzyprincepless.negotiation.services.IService;
import jfuzzyprincepless.negotiation.services.impl.AgentsListService;
import laboratoryQ.junit.ignore.patch.BaseTestCase;

public class TestConstruction extends BaseTestCase {
	public void testINegotiationConstruction() {
		INegotiationConstruction negotiationConstruction =
			new DefaultNegConstruction();
		IConstruction construction = negotiationConstruction;
		assertNotNull(construction);
		IAgentsListService als = negotiationConstruction;
		assertNotNull(als);

		INegotiationContext context = new DefaultNegotiationContext();
		context.registerService(negotiationConstruction);
		als = context.getService(IAgentsListService.class);
		assertNotNull(als);

		assertEquals(0, als.getAgentsList().size());
	}

	public void testCompoundConstruction() {
		CompoundConstruction compoundConstruction =
			new CompoundConstruction(
				new FakeCondition(0.1),
				new FakeCondition(0.3),
				new FakeCondition(0.7)
			);
		INegotiationConstruction negotiationConstruction =
			compoundConstruction;
		assertEquals(
			3,
			negotiationConstruction.getAgentsList().size()
		);

		DefaultNegotiationContext context =
			new DefaultNegotiationContext();
		context.registerService(compoundConstruction);
		try {
			context.getService(IAgentsListService.class)
				.getAgentsList().add(new FakeCondition(0.7));
			assertTrue(false);
		} catch (UnsupportedOperationException exc) {
		}

		context.registerService(
			new AgentsListService(
				new ArrayList<INegotiatingAgent>(
					context.getService(IAgentsListService.class)
						.getAgentsList()
			))
		);
		context.getService(IAgentsListService.class)
			.getAgentsList().add(new FakeCondition(0.7));
		assertEquals(
			4,
			context.getService(IAgentsListService.class)
				.getAgentsList().size()
		);

		context.getService(IAgentsListService.class)
		.getAgentsList().clear();
		assertEquals(
			0,
			context.getService(IAgentsListService.class)
				.getAgentsList().size()
		);
	}

	// ### ### ### ### ### ### ### ### ### ### ###
	private interface IServA extends IService {}
	private static class TstServConstr
		extends BaseNegotiationAgent
		implements INegotiationConstruction, IServA
	{
		@Override
		public List<INegotiatingAgent> getAgentsList() {
			return Arrays.<INegotiatingAgent>asList(this);
		}

		@Override
		public void onNegotiationStart(INegotiationContext context) {
			context.registerService(IServA.class, this);
		}
	}
	public void testCompoundDealsWithServices() {
		CompoundConstruction construction = new CompoundConstruction(
			new TstServConstr(),
			new TstServConstr()
		);
		assertEquals(2, construction.getAgentsList().size());

		INegotiationContext context = new DefaultNegotiationContext();
		context.registerService(construction);
		assertNull(context.getService(IServA.class));
		assertEquals(
			2,
			context.getService(IAgentsListService.class)
				.getAgentsList().size()
		);

		new DefaultNegotiation().negotiate(context);
		assertNotNull(context.getService(IServA.class));
		assertEquals(
			2,
			context.getService(IAgentsListService.class)
				.getAgentsList().size()
		);
	}
	// ### ### ### ### ### ### ### ### ### ### ###

	public void testWhileConstruction() {
		StringBuilder sb = new StringBuilder();
		INegotiatingAgent whlAgentA = new FakeWhileAgent("A", sb);
		INegotiatingAgent whlAgentB = new FakeWhileAgent("B", sb);
		INegotiatingAgent whlAgentC = new FakeWhileAgent("C", sb);
		INegotiationContext context = new DefaultNegotiationContext();
		FakeWhileNegConstr whileConstr =
			new FakeWhileNegConstr(whlAgentA, whlAgentB, whlAgentC);
		whileConstr.setRemaind(whlAgentA, 1);
		whileConstr.setRemaind(whlAgentB, 2);
		whileConstr.setRemaind(whlAgentC, 3);
		context.registerService(whileConstr);
		new DefaultNegotiation().negotiate(context);
		assertEquals("A, B, C, B, C, C", sb.toString());
	}
}
